home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 4 / Amiga Tools 4.iso / tools / netzwerk / parnet-filesystem / server.c < prev    next >
C/C++ Source or Header  |  1996-02-26  |  16KB  |  626 lines

  1. /*
  2.  * $Id: server.c,v 1.3 1995/11/14 00:43:34 Rhialto Exp $
  3.  * $Log: server.c,v $
  4.  * Revision 1.3  1995/11/14  00:43:34  Rhialto
  5.  * More casts for yet stricter DICE type checking...
  6.  *
  7.  * Revision 1.2  1995/11/14  00:08:15  Rhialto
  8.  * #ifdef -> #if; cater to stricter compiler; typos.
  9.  *
  10.  * Revision 1.1  1993/12/02  20:45:46  Rhialto
  11.  * Initial revision
  12.  *
  13.  * The bulk of the server code: receive packets and act upon them.
  14.  */
  15.  
  16. #include "netfs.h"
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include "getopt.c"
  20.  
  21. #if DEBUG
  22. #   include "syslog.h"
  23. #else
  24. #   define    debug(x)
  25. #endif
  26.  
  27. long        UnitNr;
  28. char           *DevName = "parnet.device";
  29. ULONG        DevFlags;
  30. struct DosPacket *DosPkt;
  31. ULONG        WaitMask;
  32. ULONG        Validation;
  33. ULONG        MyValidation;
  34. struct MsgPort *DosPort;
  35. struct MsgPort *AsyncDosPort;
  36. struct Process *Proc;
  37. void           *pr_WindowPtr = (void *)-2;
  38.  
  39. void
  40. chkabort(void)
  41. {
  42.     /* do not check for break */
  43. }
  44.  
  45. void
  46. dumppkt(Packet *pkt)
  47. {
  48.     debug(("Packet: %08lx; %08lx, %08lx %08lx %08lx %08lx %08lx\n",
  49.       *(long *)pkt, pkt->p_Action,
  50.       pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2],
  51.       pkt->p_Arg[3], pkt->p_Arg[4], pkt->p_Arg[5]));
  52. }
  53.  
  54. Prototype ULONG dopacket(struct DosPacket *packet, struct MsgPort *port);
  55.  
  56. ULONG
  57. dopacket(struct DosPacket *packet, struct MsgPort *port)
  58. {
  59.     packet->dp_Port = DosPort;
  60.  
  61.     PutMsg(port, packet->dp_Link);
  62.     WaitPort(DosPort);
  63.     GetMsg(DosPort);
  64.  
  65.     return packet->dp_Res1;
  66. }
  67.  
  68. void
  69. doasyncpacket(struct DosPacket *packet, struct MsgPort *port)
  70. {
  71.     packet->dp_Port = AsyncDosPort;
  72.  
  73.     PutMsg(port, packet->dp_Link);
  74. }
  75.  
  76. /*
  77.  * Create a DOS style packet: a message and a dos packet linked to
  78.  * each other. The size of the message is variable so you can include
  79.  * extra information behind it, or use it as an I/O request.
  80.  */
  81.  
  82. struct DosPacket *
  83. CreateDosPkt(int size)
  84. {
  85.     struct DosPacket *dp;
  86.     struct Message *msg;
  87.  
  88.     size += sizeof(struct Message) + sizeof(struct DosPacket);
  89.  
  90.     if (msg = AllocMem(size, MEMF_PUBLIC | MEMF_CLEAR)) {
  91.     dp = (struct DosPacket *)
  92.          ((char *)msg + size - sizeof(struct DosPacket));
  93.  
  94.     dp->dp_Link = msg;
  95.     msg->mn_Node.ln_Name = (char *)dp;
  96.     msg->mn_Length = size;
  97.     }
  98.     return dp;
  99. }
  100.  
  101. void
  102. DeleteDosPkt(struct DosPacket *dp)
  103. {
  104.     if (dp) {
  105.     struct Message *msg = dp->dp_Link;
  106.  
  107.     FreeMem(msg, msg->mn_Length);
  108.     }
  109. }
  110.  
  111. struct MsgPort *
  112. FindProc(BPTR fl, char *bstr)
  113. {
  114.     struct FileLock *lock;
  115.  
  116.     if (strchr(bstr + 1, ':')) {
  117.     return DeviceProc(bstr + 1);
  118.     }
  119.  
  120.     lock = BTOC(fl);
  121.  
  122.     return lock->fl_Task;
  123. }
  124.  
  125. UBYTE *
  126. SkipString(UBYTE *s)
  127. {
  128.     s = s + s[0] + 2;
  129.     s = (UBYTE *)((ULONG)(s + 3) & ~3);
  130.     return s;
  131. }
  132.  
  133. /* ---------------------------------------------------------------------- */
  134.  
  135. void
  136. HandleRequest(struct IOParReq *io, Packet *pkt)
  137. {
  138.     LONG        tmp;
  139.     ULONG        replysize;
  140.  
  141.     debug(("type %d action %d\n", pkt->p_Type, pkt->p_Action));
  142.  
  143.     switch (DoProtocol(io, pkt)) {
  144.     case pt_Request:
  145.     break;
  146.     default:
  147.     return;
  148.     }
  149.  
  150.     /* Now we know it's a request, we can do something about it. */
  151.  
  152.     replysize = STDREPLY;
  153.     Proc->pr_Result2 = 0;
  154.  
  155.     switch (pkt->p_Action) {
  156. /*  case ACTION_DIE:           / *  attempt to die?             */
  157. /*  case ACTION_CURRENT_VOLUME:/ * -               VolNode,UnitNr*/
  158.     case ACTION_RENAME_DISK:    /* New name           Bool      */
  159.     {
  160.         char *newname;
  161.  
  162.         newname = SkipString((char *)&pkt->p_Arg[0])+1;
  163.         debug(("Relabel '%s' -> '%s'\n", ((char *)&pkt->p_Arg[0])+1, newname));
  164.         pkt->p_Res1 = Relabel((char *)&pkt->p_Arg[0]+1, newname);
  165.         pkt->p_Res2 = Proc->pr_Result2;
  166.     }
  167.     break;
  168.     case ACTION_LOCATE_OBJECT:    /* Lock,Name,Mode    Lock         */
  169.     tmp = CurrentDir(pkt->p_Arg[0]);
  170.     pkt->p_Res1 = Lock((char *)&pkt->p_Arg[2]+1, pkt->p_Arg[1]);
  171.     pkt->p_Res2 = Proc->pr_Result2;
  172.     CurrentDir(tmp);
  173.     break;
  174.     case ACTION_FREE_LOCK:    /* Lock            Bool      */
  175.     UnLock(pkt->p_Arg[0]);
  176.     pkt->p_Res1 = DOSTRUE;
  177.     pkt->p_Res2 = Proc->pr_Result2;
  178.     break;
  179.     case ACTION_DELETE_OBJECT:    /* Lock,Name        Bool         */
  180.     tmp = CurrentDir(pkt->p_Arg[0]);
  181.     pkt->p_Res1 = DeleteFile((char *)&pkt->p_Arg[1]+1);
  182.     pkt->p_Res2 = Proc->pr_Result2;
  183.     CurrentDir(tmp);
  184.     break;
  185.     case ACTION_RENAME_OBJECT:    /* SLock,SName,DLock,DName   Bool    */
  186.     {
  187.         struct MsgPort *handler;
  188.         char *sname;
  189.         char *dname;
  190.  
  191.         sname = (char *)(&pkt->p_Arg[2]);
  192.         dname = SkipString(sname);
  193.  
  194.         DosPkt->dp_Action = ACTION_RENAME_OBJECT;
  195.         DosPkt->dp_Arg1 = pkt->p_Arg[0];
  196.         DosPkt->dp_Arg2 = CTOB(sname);
  197.         DosPkt->dp_Arg3 = pkt->p_Arg[1];
  198.         DosPkt->dp_Arg4 = CTOB(dname);
  199.  
  200.         handler = FindProc(pkt->p_Arg[0], sname+1);
  201.         if (handler == NULL)
  202.         handler = FindProc(pkt->p_Arg[1], dname+1);
  203.         if (handler != NULL) {
  204.         dopacket(DosPkt, handler);
  205.  
  206.         pkt->p_Res1 = DosPkt->dp_Res1;
  207.         pkt->p_Res2 = DosPkt->dp_Res2;
  208.         } else {
  209.         pkt->p_Res1 = DOSFALSE;
  210.         pkt->p_Res2 = ERROR_INVALID_LOCK;
  211.         }
  212.     }
  213.     break;
  214.     case ACTION_COPY_DIR:    /* Lock            Lock      */
  215.     pkt->p_Res1 = DupLock(pkt->p_Arg[0]);
  216.     pkt->p_Res2 = Proc->pr_Result2;
  217.     break;
  218.     case ACTION_SET_PROTECT:    /* -,Lock,Name,Mask       Bool      */
  219.     tmp = CurrentDir(pkt->p_Arg[0]);
  220.     pkt->p_Res1 = SetProtection((char *)&pkt->p_Arg[2]+1, pkt->p_Arg[1]);
  221.     pkt->p_Res2 = Proc->pr_Result2;
  222.     CurrentDir(tmp);
  223.     break;
  224.     case ACTION_CREATE_DIR:    /* Lock,Name        Lock         */
  225.     tmp = CurrentDir(pkt->p_Arg[0]);
  226.     pkt->p_Res1 = CreateDir((char *)&pkt->p_Arg[1]+1);
  227.     pkt->p_Res2 = Proc->pr_Result2;
  228.     CurrentDir(tmp);
  229.     break;
  230. /*
  231.  * Note that for ExNext() the FileInfoBlock is copied from the client
  232.  * to the server, and back again. This is because ExNext needs the fib
  233.  * to be initialised by a previous call. In fact, it even may insist
  234.  * on the *very same* fib to be used in each call in a sequence.
  235.  * Possibly it may even require that several simultaneous scans of the
  236.  * same directory use *different* fibs. Obviously, we can't comply with
  237.  * those requirements. For the moment it seems to work ok, but who knows
  238.  * it might break in the future!
  239.  * Also, because the fib is copied in and out, we refer to it through
  240.  * the incoming field names of the packet exclusively. Care must be
  241.  * taken with overlapping fields in request and reply.
  242.  */
  243.     case ACTION_EXAMINE_OBJECT: /* Lock,Fib           Bool         */
  244.     case ACTION_EXAMINE_NEXT:    /* Lock,Fib           Bool         */
  245.     DosPkt->dp_Action = pkt->p_Action;
  246.     DosPkt->dp_Arg1 = pkt->p_Arg[0];
  247.     DosPkt->dp_Arg2 = CTOB(&pkt->p_Arg[1]);
  248.  
  249.     dopacket(DosPkt, ((struct FileLock *)BTOC(pkt->p_Arg[0]))->fl_Task);
  250.  
  251.     pkt->p_Res2 = DosPkt->dp_Res2;
  252.     if (pkt->p_Res1 = DosPkt->dp_Res1)
  253.         replysize = STDREPLY + sizeof(struct FileInfoBlock);
  254. #if xDEBUG
  255.     {
  256.         struct FileInfoBlock *fib;
  257.         fib = (struct FileInfoBlock *)&pkt->p_Data[0];
  258.         debug(("key %x size %d name '%.*s'\n", fib->fib_DiskKey, fib->fib_Size,
  259.             fib->fib_FileName[0], &fib->fib_FileName[1]));
  260.     }
  261. #endif
  262.     break;
  263. /*  case ACTION_DISK_INFO:     / * InfoData           Bool:TRUE     */
  264.     case ACTION_INFO:    /* Lock,InfoData           Bool:TRUE     */
  265.     pkt->p_Res1 = Info(pkt->p_Arg[0], (void *)&pkt->p_Data[0]);
  266.     pkt->p_Res2 = Proc->pr_Result2;
  267.     if (pkt->p_Res1)
  268.         replysize = STDREPLY + sizeof(struct InfoData);
  269.     break;
  270. /*  case ACTION_FLUSH:           / * writeout bufs, disk motor off     */
  271.     case ACTION_SET_COMMENT:    /* -,Lock,Name,Comment       Bool      */
  272.     tmp = CurrentDir(pkt->p_Arg[0]);
  273.     pkt->p_Res1 = SetComment((char *)&pkt->p_Arg[1]+1,
  274.                  SkipString((char *)&pkt->p_Arg[1])+1);
  275.     pkt->p_Res2 = Proc->pr_Result2;
  276.     CurrentDir(tmp);
  277.     break;
  278.     break;
  279.     case ACTION_PARENT: /* Lock                ParentLock    */
  280.     pkt->p_Res1 = ParentDir(pkt->p_Arg[0]);
  281.     pkt->p_Res2 = Proc->pr_Result2;
  282.     break;
  283. /*  case ACTION_INHIBIT:       / * Bool            Bool      */
  284.     case ACTION_SET_DATE: /* -,Lock,Name,CPTRDateStamp       Bool      */
  285.     tmp = CurrentDir(pkt->p_Arg[0]);
  286. /*V37*/ pkt->p_Res1 = SetFileDate((char *)&pkt->p_Arg[4]+1,
  287.                   (struct DateStamp *)&pkt->p_Arg[1]);
  288.     pkt->p_Res2 = Proc->pr_Result2;
  289.     CurrentDir(tmp);
  290.     break;
  291.     case ACTION_SAME_LOCK:  /* Lock1,Lock2           Result    */
  292.     if (pkt->p_Arg[0] == 0 || pkt->p_Arg[1] == 0) {
  293.         /* We never send 0 locks */
  294.         pkt->p_Res1 = DOSFALSE;
  295.         pkt->p_Res2 = ERROR_INVALID_LOCK;
  296.     } else {
  297.         DosPkt->dp_Action = ACTION_SAME_LOCK;
  298.         DosPkt->dp_Arg1 = pkt->p_Arg[0];
  299.         DosPkt->dp_Arg2 = pkt->p_Arg[1];
  300.  
  301.         dopacket(DosPkt, ((struct FileLock *)BTOC(pkt->p_Arg[0]))->fl_Task);
  302.  
  303.         pkt->p_Res1 = DosPkt->dp_Res1;
  304.         pkt->p_Res2 = DosPkt->dp_Res2;
  305.     }
  306.     break;
  307.     case ACTION_READ:    /* FHArg1,CPTRBuffer,Length      ActLength  */
  308.     tmp = Read(pkt->p_Arg[0], &pkt->p_Data[0], pkt->p_Arg[1]);
  309.     pkt->p_Res1 = tmp;
  310.     pkt->p_Res2 = Proc->pr_Result2;
  311.     if (tmp > 0)
  312.         replysize = STDREPLY + tmp;
  313.     break;
  314.     case ACTION_WRITE:    /* FHArg1,CPTRBuffer,Length      ActLength  */
  315.     pkt->p_Res1 = Write(pkt->p_Arg[0], &pkt->p_Arg[2], pkt->p_Arg[1]);
  316.     pkt->p_Res2 = Proc->pr_Result2;
  317.     break;
  318.     case ACTION_OPENRW:     /* FileHandle,Lock,Name    Bool      */
  319.     case ACTION_OPENOLD:    /* FileHandle,Lock,Name    Bool      */
  320.     case ACTION_OPENNEW:    /* FileHandle,Lock,Name    Bool      */
  321.     tmp = CurrentDir(pkt->p_Arg[0]);
  322.     pkt->p_Res1 = Open((char *)&pkt->p_Arg[1]+1, pkt->p_Action);
  323.     pkt->p_Res2 = Proc->pr_Result2;
  324.     CurrentDir(tmp);
  325.     break;
  326.     case ACTION_CLOSE:    /* FHArg1            Bool:Success */
  327.     pkt->p_Res1 = Close(pkt->p_Arg[0]);
  328.     pkt->p_Res2 = Proc->pr_Result2;
  329.     break;
  330.     case ACTION_SEEK:    /* FHArg1,Position,Mode      OldPosition */
  331.     pkt->p_Res1 = Seek(pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2]);
  332.     pkt->p_Res2 = Proc->pr_Result2;
  333.     break;
  334. #ifdef notdef
  335.     case ACTION_FORMAT: /* vol,type            Bool:success */
  336.     break;
  337. #endif
  338.     case ACTION_MAKE_LINK: /* parent,name,target,mode       Bool      */
  339.     {
  340.         ULONG soft;
  341.  
  342.         tmp = CurrentDir(pkt->p_Arg[0]);
  343.         soft = pkt->p_Arg[1];
  344.         dumppkt(pkt);
  345.         if (soft) {
  346.         debug(("MakeLink soft '%s' -> '%s'\n",
  347.                SkipString((char *)&pkt->p_Arg[2])+1,
  348.                (char *)&pkt->p_Arg[2]+1));
  349. /*V37*/     pkt->p_Res1 = MakeLink(SkipString((char *)&pkt->p_Arg[2])+1,
  350.                        (ULONG)(char *)&pkt->p_Arg[2]+1,
  351.                        soft);
  352.         } else {
  353.         pkt->p_Res1 = MakeLink((char *)&pkt->p_Arg[3]+1,
  354.                        pkt->p_Arg[2],
  355.                        soft);
  356.         }
  357.         pkt->p_Res2 = Proc->pr_Result2;
  358.         CurrentDir(tmp);
  359.     }
  360.     break;
  361.     case ACTION_READ_LINK: /* parent,name,target,size       length    */
  362.     {
  363.         struct FileLock *fl;
  364.         ULONG        size;
  365.  
  366.         fl = BTOC(pkt->p_Arg[0]);
  367.         size = min(pkt->p_Arg[1], MAXDATA);
  368.  
  369. /*V37*/     pkt->p_Res1 = ReadLink(fl->fl_Task,
  370.                    pkt->p_Arg[0],
  371.                    (char *)&pkt->p_Arg[2]+1,
  372.                    (char *)&pkt->p_Data[0],
  373.                    size);
  374.         pkt->p_Res2 = Proc->pr_Result2;
  375.         if (pkt->p_Res1 >= 0)
  376.         replysize = STDREPLY + pkt->p_Res1;
  377.     }
  378.     break;
  379.     case ACTION_SET_FILE_SIZE:
  380. /*V37*/ pkt->p_Res1 = SetFileSize(pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2]);
  381.     pkt->p_Res2 = Proc->pr_Result2;
  382.     break;
  383. /*  case ACTION_WRITE_PROTECT: */
  384.     case ACTION_FH_FROM_LOCK: /* FH,Lock            BOOL     */
  385. /*V37*/ pkt->p_Res1 = OpenFromLock(pkt->p_Arg[0]);
  386.     pkt->p_Res2 = Proc->pr_Result2;
  387.     break;
  388.     case ACTION_CHANGE_MODE:
  389. /*V37*/ pkt->p_Res1 = ChangeMode(pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2]);
  390.     pkt->p_Res2 = Proc->pr_Result2;
  391.     break;
  392.     case ACTION_COPY_DIR_FH:    /* fh_Arg1           Lock      */
  393. /*V37*/ pkt->p_Res1 = DupLockFromFH(pkt->p_Arg[0]);
  394.     pkt->p_Res2 = Proc->pr_Result2;
  395.     break;
  396.     case ACTION_PARENT_FH:
  397. /*V37*/ pkt->p_Res1 = ParentOfFH(pkt->p_Arg[0]);
  398.     pkt->p_Res2 = Proc->pr_Result2;
  399.     break;
  400.     case ACTION_EXAMINE_FH:    /* fh_Arg1,Fib           Bool      */
  401.     {
  402.         struct FileHandle *fh;
  403.  
  404.         fh = (struct FileHandle *)BTOC(pkt->p_Arg[0]);
  405.         DosPkt->dp_Action = ACTION_EXAMINE_FH;
  406.         DosPkt->dp_Arg1 = fh->fh_Arg1;
  407.         DosPkt->dp_Arg2 = CTOB(&pkt->p_Data[0]);
  408.  
  409.         dopacket(DosPkt, fh->fh_Type);
  410.  
  411.         pkt->p_Res2 = DosPkt->dp_Res2;
  412.         if (pkt->p_Res1 = DosPkt->dp_Res1)
  413.         replysize = STDREPLY + sizeof(struct FileInfoBlock);
  414.     }
  415.     break;
  416.     case ACTION_LOCK_RECORD:    /* fh,pos,len,mode,time    Bool      */
  417.     {
  418.         struct DosPacket *dp;
  419.         struct FileHandle *fh;
  420.  
  421.         fh = (struct FileHandle *)BTOC(pkt->p_Arg[0]);
  422.         dp = CreateDosPkt(2*sizeof(long));
  423.         debug(("LOCK_RECORD %x, dp %x\n", fh, dp));
  424.         dp->dp_Action = ACTION_LOCK_RECORD;
  425.         dp->dp_Arg1 = fh->fh_Arg1;
  426.         dp->dp_Arg2 = pkt->p_Arg[1];
  427.         dp->dp_Arg3 = pkt->p_Arg[2];
  428.         dp->dp_Arg4 = pkt->p_Arg[3];
  429.         dp->dp_Arg5 = pkt->p_Arg[4];
  430.  
  431.         ((long *)dp)[-1] = pkt->p_Origin;
  432.         ((long *)dp)[-2] = pkt->p_Arg[5];     /* client cookie */
  433.  
  434.         doasyncpacket(dp, fh->fh_Type);
  435.     }
  436.     break;
  437.     case ACTION_FREE_RECORD:    /* fh,pos,len           Bool      */
  438. /*V37*/ pkt->p_Res1 = UnLockRecord(pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2]);
  439.     pkt->p_Res2 = Proc->pr_Result2;
  440.     break;
  441.     default:
  442.     pkt->p_Res1 = DOSFALSE;
  443.     pkt->p_Res2 = ERROR_ACTION_NOT_KNOWN;
  444.     break;
  445.     }
  446.  
  447.     debug(("res: %d err: %d\n", pkt->p_Res1, pkt->p_Res2));
  448.     DoReply(io, pkt, replysize);
  449. }
  450.  
  451. void
  452. HandleAsyncDosPkt(struct Message *msg)
  453. {
  454.     char        buf[STDREPLY + 2*sizeof(long)];
  455.     Packet       *p = (Packet *)buf;
  456.     struct DosPacket *dp = (struct DosPacket *)msg->mn_Node.ln_Name;
  457.  
  458.     debug(("HandleAsyncDosPkt(msg %x) dp %x res: %x/%d\n",
  459.        msg, dp, dp->dp_Res1, dp->dp_Res2));
  460.  
  461.     p->p_Res1 = dp->dp_Res1;
  462.     p->p_Res2 = dp->dp_Res2;
  463.     p->p_Data[0] = dp->dp_Action;
  464.  
  465.     switch (dp->dp_Action) {
  466.     case ACTION_LOCK_RECORD:
  467.     p->p_Origin  = ((long *)dp)[-1];
  468.     p->p_Data[1] = ((long *)dp)[-2];            /* client cookie */
  469.     break;
  470.     default:
  471.     debug(("Funny DOS packet returning %x %d\n", msg, dp->dp_Action));
  472.     goto end;
  473.     }
  474.  
  475.     DoReplyAsync(ParReq, p, sizeof(buf));
  476.     DeleteDosPkt(dp);
  477.  
  478. end:;
  479. }
  480.  
  481. /* ---------------------------------------------------------------------- */
  482.  
  483. Prototype void DoAsyncReply(Packet *pkt);
  484.  
  485. void
  486. DoAsyncReply(Packet *pkt)
  487. {
  488.     debug(("We're not supposed to get these!\n"));
  489. }
  490.  
  491.  
  492. /* ---------------------------------------------------------------------- */
  493.  
  494. ULONG
  495. InitServer(void)
  496. {
  497.     debug(("InitServer\n"));
  498.  
  499.     DosPkt = CreateDosPkt(0);
  500.     DosPort = CreatePort("NetServer DosPort", -1);
  501.     AsyncDosPort = CreatePort("NetServer AsyncDosPort", -1);
  502.  
  503.     WaitMask = 1L << RdPort->mp_SigBit |
  504.            1L << AsyncDosPort->mp_SigBit |
  505.            SIGBREAKF_CTRL_C;
  506.  
  507.     Proc = (struct Process *)FindTask(NULL);
  508.     pr_WindowPtr = Proc->pr_WindowPtr;
  509.     Proc->pr_WindowPtr = (void *)-1;
  510.  
  511.     return 0;
  512. }
  513.  
  514. void
  515. CleanupServer(void)
  516. {
  517.     debug(("CleanupServer\n"));
  518.     if (pr_WindowPtr != (void *)-2)
  519.     Proc->pr_WindowPtr = pr_WindowPtr;
  520.     if (DosPkt) {
  521.     DeleteDosPkt(DosPkt);
  522.     DosPkt = NULL;
  523.     }
  524. }
  525.  
  526. void
  527. ServeLoop(void)
  528. {
  529.     ULONG        sigs;
  530.  
  531.     while (1) {
  532.     debug(("ServeLoop: Wait ...\n"));
  533.     sigs = Wait(WaitMask);
  534.     {
  535.         struct Message *msg;
  536.  
  537.         while (msg = GetMsg(AsyncDosPort)) {
  538.         HandleAsyncDosPkt(msg);
  539.         }
  540.     }
  541.     if (sigs & SIGBREAKF_CTRL_C)
  542.         break;
  543.     {
  544.         struct IOParReq *io;
  545.         Packet       *pkt;
  546.  
  547.         while (io = (struct IOParReq *)GetMsg(RdPort)) {
  548.         pkt = ((struct IOStdReq *)io)->io_Data;
  549.         if (((struct IOStdReq *)io)->io_Error == 0)
  550.             HandleRequest(io, pkt);
  551.         else
  552.             DoReset(ParReq);
  553.         SendRead(io, pkt, PKTSIZE);
  554.         }
  555.     }
  556.     }
  557. }
  558.  
  559. /* ---------------------------------------------------------------------- */
  560.  
  561. int
  562. main(int argc, char **argv)
  563. {
  564.     int         c;
  565.  
  566. #if DEBUG
  567.     initsyslog();
  568. #endif                /* DEBUG */
  569.  
  570.     if (DOSBase->dl_lib.lib_Version < 37) {
  571.     Write(Output(),
  572.         "You should upgrade to at least 2.0 as soon as possible!\n"
  573.         "If any client uses a 2.0+ packet, you will crash!\n", 106);
  574.     }
  575.  
  576.     /* Primary defaults */
  577.     MyAddr = SRV_ADDR;
  578.     PeerAddr = CLI_ADDR;
  579.     NetFSPort = NETFS_PORT;
  580.  
  581.     while ((c = getopt(argc, argv, "sd:u:f:p:a:c:")) != -1) {
  582.     switch (c) {
  583.     case 's':
  584.         /* Secondary server/client */
  585.         MyAddr = CLI_ADDR;
  586.         PeerAddr = SRV_ADDR;
  587.         NetFSPort = NETFS_PORT + 1;
  588.         break;
  589.     case 'd':
  590.         DevName = optarg;
  591.         break;
  592.     case 'u':
  593.         UnitNr = strtol(optarg, NULL, 0);
  594.         break;
  595.     case 'f':
  596.         DevFlags = strtol(optarg, NULL, 0);
  597.         break;
  598.     case 'p':
  599.         NetFSPort = strtol(optarg, NULL, 0);
  600.         break;
  601.     case 'a':
  602.         MyAddr = strtol(optarg, NULL, 0);
  603.         break;
  604.     case 'c':
  605.         PeerAddr = strtol(optarg, NULL, 0);
  606.         break;
  607.     case '?':
  608.         return 20;
  609.     }
  610.     }
  611.  
  612.     debug(("call OpenNetwork\n"));
  613.     if (OpenNetwork())
  614.     return 20;
  615.  
  616.     if (InitServer() == 0) {
  617.     ServeLoop();
  618.     CleanupServer();
  619.     }
  620.  
  621.     CloseNetwork();
  622. #if DEBUG
  623.     uninitsyslog();
  624. #endif                /* DEBUG */
  625. }
  626.